<!DOCTYPE HTML>
<html>
<head>
    <title>MINIMMORTS HTML5 client</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <script type="text/javascript" src="js/constants.js"></script>
    <script type="text/javascript" src="js/resources.js"></script>
    <script type="text/javascript" src="js/routines.js"></script>
    
    <script type="text/javascript" src="js/Camera.js"></script>
    <script type="text/javascript" src="js/Unit.js"></script>
    <script type="text/javascript" src="js/SpriteLoader.js"></script>
    <script type="text/javascript" src="js/Map.js"></script>
    <script type="text/javascript" src="js/Movement.js"></script>
    <script type="text/javascript" src="js/MovementManager.js"></script>
    <script type="text/javascript" src="js/messages.js"></script>
    <script type="text/javascript" src="js/ServerInteraction.js"></script>
    <script type="text/javascript" src="js/Sprite.js"></script>
    <script type="text/javascript" src="js/SpriteMovement.js"></script>
    <script type="text/javascript" src="js/SpriteMovementWayPoint.js"></script>
    <style type="text/css" >
    #scr {
        border: 1px solid #000000;
    }
    #login_form {
        background-color: tan;
        z-index: 1;
        position: absolute;
        top: 300px;
        left: 300px;
        visibility: hidden;
    }
    </style>
</head>
<body onunload="disconnect(); return false;">

<script type="text/javascript">

/*********************
 * Создание холстов. *
 *********************/

// Основной холст, который будет показан клиенту.

var scr = document.createElement('canvas');
scr.id = "scr";
scr.width = SCR_W;
scr.height = SCR_H;
scr.oncontextmenu = function() {
    return false;  
}
// Добавление обработчика щелчка мышью происходит при запуске игры.
var body = document.getElementsByTagName('body')[0];
body.appendChild(scr);

// Холст для рисования карты.

var map_buffer = document.createElement('canvas');
map_buffer.width = SCR_W;
map_buffer.height = SCR_H;

// Холст для рисования игроков.

var units_buffer = document.createElement('canvas');
units_buffer.width = SCR_W;
units_buffer.height = SCR_H;

/*************************
 * Служебные переменные. *
 *************************/

// debug
var DEBUG = true;

var DEBUG_PROTOCOL = true;

var DEBUG_UNITS = true;

var DEBUG_MOVEMENTS = true;

// Список юнитов, принадлежащих клиенту.
var self_units_list = new Array();

// Список юнитов.
var units_list = new Array();

// Карта.
var map;

// Сервер.
var server;

// Камера. В её объекиве находится место, которое будет нарисовано на основном холсте.
var camera;

// Камера свободна или привязана к своему игроку.
var is_camera_free = false;

// Буфер действий.
var actions = new Array();

// Действия, которые должны быть выполнены после получения подтверждения.
var stored_actions;

// Номер текущего хода.
var step;

// Id этого клиента.
var clientId;

// Выделенные юниты.
var selected_units = new Array();

// Клетка начала выделения.
var selections_beg;

// Прямоугольник выделения.
var selection_rect = null;

// Менеджер движения.
var movementManager = new MovementManager();

// Получено ли начальное состояние.
var is_initial_state_received = false;

var smoothMovementEnabled = true;

var prevDrawTime = null;

var drawTimer = null;

var syncTimer = null;

var saveUnitHistory = false;

/************
 * Функции. *
 ************/

function connect() {
    if (server == undefined) {
        server = new ServerInteraction()
        server.connect(document.getElementById('host').value)
    } else if (server.socket.readyState == WebSocket.OPEN) {
        server.sendMessage(new LoginMessage(getLogin(), getPassword()))
    } else {
        server.connect(document.getElementById('host').value)
    }
        
    return false
}

function disconnect() {
    if (server != undefined && server.socket != null) {
        server.socket.close()
    }
}

function drawLoop() {
    var scr_context = scr.getContext('2d');
    var units_context = units_buffer.getContext('2d');
    var map_context = map_buffer.getContext('2d');
    var i;

    // Фон.
    scr_context.fillStyle = "#FFFFEE";
    scr_context.fillRect(0, 0, scr.width, scr.height);

    // Пока что будем очищать весь холст целиком, а не только область, в которой было что-то нарисовано.
    units_context.clearRect(0, 0, units_buffer.width, units_buffer.height);
    map_context.clearRect(0, 0, map_buffer.width, map_buffer.height);

    // Нарисуем карту.
    map.draw(map_context, camera);
    
    // Обновим позиции спрайтов юнитов.
    movementManager.updateSpritePositions();

    // Нарисуем юнитов, принадлежащих клиенту.
    for (i in self_units_list) {
        self_units_list[i].draw(units_context, camera);
        //self_units_list[i].drawPath(units_context, camera);
    }

    // Нарисуем остальных юнитов.
    for (i in units_list) {
        units_list[i].draw(units_context, camera);
        //units_list[i].drawPath(units_context, camera);
    }
    
    if (selection_rect != null) {
        selection_rect.draw(units_context, camera);
    }
    
    units_context.putImageData(
        map.miniMap,
        10,
        10
    );

    // Нарисуем карту и юнитов на основном холсте.
    scr_context.drawImage(map_buffer, 0, 0);
    scr_context.drawImage(units_buffer, 0, 0);
    //scr_context.fillText("FPStep=" + getFramesPerStep(), 100, 100);
    //scr_context.fillText("PXIncr=" + getPxIncrement(0.4), 100, 110);

    drawTimer = setTimeout(drawLoop, 1000 / FPS);
}

function scrOnMousedown(e) {
    var x;
    var y;
    if (e.pageX != undefined && e.pageY != undefined) {
        x = e.pageX;
        y = e.pageY;
    } else {
        x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
        y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
    }
    x -= scr.offsetLeft;
    y -= scr.offsetTop;
    
    if (e.button == 0) {
        selections_beg = {x1: x, y1: y}
        scr.addEventListener("mousemove", scrOnMousemove, false);
    }
}

function scrOnMouseup(e) {
    var x;
    var y;
    if (e.pageX != undefined && e.pageY != undefined) {
        x = e.pageX;
        y = e.pageY;
    } else {
        x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
        y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
    }
    x -= scr.offsetLeft;
    y -= scr.offsetTop;
    
    if (e.button == 0) {
        selected_units = new Array();
        selection_rect = createSelectionRect(selections_beg.x1, selections_beg.y1, x, y);
        
        for (var i in self_units_list) {
            if (self_units_list[i].j >= selection_rect.beg.j
                    && self_units_list[i].j <= selection_rect.end.j
                    && self_units_list[i].i >= selection_rect.beg.i
                    && self_units_list[i].i <= selection_rect.end.i) {
                
                self_units_list[i].selected = true;
                selected_units.push(self_units_list[i]);
            } else {
                self_units_list[i].selected = false;
            }
        }
        scr.removeEventListener("mousemove", scrOnMousemove, false);
        selection_rect = null;
    } else if (e.button == 2) {
        var tAxis = camera.reTranslateAxis(x, y);
        var neighbourCells = new Array({j: Map.getCellJOnMap(tAxis.x), i: Map.getCellIOnMap(tAxis.y)});
        while (neighbourCells.length < selected_units.length && neighbourCells.length < map.w * map.h) {
            neighbourCells = getNeighboursCells(neighbourCells);
        }
        for (var i = 0; i < Math.min(neighbourCells.length, selected_units.length); i++) {
            if (selected_units[i].getJ() == neighbourCells[i].j && selected_units[i].getI() == neighbourCells[i].i) {
                continue;
            }
            actions.push(
                new MoveMessage(
                    step,
                    selected_units[i].getId(),
                    -1,
                    -1,
                    neighbourCells[i].j,
                    neighbourCells[i].i
                )
            );
        }
    }
}

function scrOnMousemove(e) {
    var x;
    var y;
    if (e.pageX != undefined && e.pageY != undefined) {
        x = e.pageX;
        y = e.pageY;
    } else {
        x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
        y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
    }
    x -= scr.offsetLeft;
    y -= scr.offsetTop;
    
    selection_rect = createSelectionRect(selections_beg.x1, selections_beg.y1, x, y);
}

function syncLoop() {
    var i, unit;
    
    for (i in stored_actions) {
        switch (stored_actions[i].type) {
            case "MOVE":
                if ( (unit = getUnitById(stored_actions[i].unitId)) == null) {
                    console.log("Сохранённое действие не может быть выполнено. Юнит id=" + stored_actions[i].unitId + " не найден.");
                    continue;
                }
                if (movementManager.isUnitMove(unit)) {
                    movementManager.updateMovement(
                        step,
                        unit,
                        stored_actions[i].endJ,
                        stored_actions[i].endI
                    );
                } else {
                    movementManager.startNewMovement(
                        step,
                        unit,
                        unit.getJ(),
                        unit.getI(),
                        stored_actions[i].endJ,
                        stored_actions[i].endI
                    );
                    //console.log("Movement created on step ", step);
                }
                break;
        }
    }
    
    step++;
    
    movementManager.updatePositions(step);
    map.updateMinimap();

    var unitMessages = new Array();
    for (i in self_units_list) {
        unitMessages.push(new UnitMessage(self_units_list[i].getOwnerId(), self_units_list[i].getId(), self_units_list[i].getJ(), self_units_list[i].getI()));
    }
    for (i in units_list) {
        unitMessages.push(new UnitMessage(units_list[i].getOwnerId(), units_list[i].getId(), units_list[i].getJ(), units_list[i].getI()));
    }
    server.sendMessage(new MessagePacket(new StateReportMessage(step, unitMessages, actions)));
    stored_actions = actions;
    actions = new Array();
}

</script>

<!-- Форма логина. -->
<div id="login_form">
Login: <input type="text" id="login" value="test"><br>
Password: <input type="password" id="password" value="test"><br>
Server: <input type="text" id="host" value="ws://localhost:8015/"><br>
<input type="button" id="connect_button" value="Connect" onclick="connect(); return false;">
</div>

<br>
<input type="checkbox" id="toggleSmoothMovement" onclick="toggleSmoothMovement();" checked>
<b>Плавное движение</b> (юнит двигается плавно, но при этом, в случае лагов, может отображаться не в том месте, где на самом деле находся)<br>

<script type="text/javascript">
showLoginForm();
document.getElementById('toggleSmoothMovement').checked = smoothMovementEnabled;
    
document.onkeydown = function(event) {
    var events = event || window.event
    if (events.keyCode == 116) {    // F5
        disconnect();
    }
    if (camera != undefined && camera.target == undefined && events.keyCode == 37) {    // left arrow 
        camera.x -= 1 * CELL_W;
    }
    if (camera != undefined && camera.target == undefined && events.keyCode == 38) {    // up arrow 
        camera.y -= 1 * CELL_H;
    }
    if (camera != undefined && camera.target == undefined && events.keyCode == 39) {    // right arrow
        camera.x += 1 * CELL_W;
    }
    if (camera != undefined && camera.target == undefined && events.keyCode == 40) {    // down arrow
        camera.y += 1 * CELL_H;
    }
}
</script>

</body>
</html>
